package com.dl698.axdr;

import com.dl698.asn1.axdr.AxdrType;
import com.dl698.asn1.axdr.AxdrNull;
import com.dl698.asn1.axdr.AxdrEnum;
import com.dl698.util.ReverseByteArrayInputStream;
import com.dl698.util.ReverseByteArrayOutputStream;

/**
 * MS类
 * 实现成员集的编解码
 * 
 * @author wind
 * @version 1.1.1
 */
public class MS implements AxdrType {

    private byte[] dataCode = null;
    private MSChoice choice = MSChoice._ERR_NONE_SELECTED;
    private AxdrNull nom = null;
    private AxdrNull allmaddr = null;
    private SubSeqOfUnsigned8 groupmtype = null;
    private SubSeqOfTsa groupmaddr = null;
    private SubSeqOfUnsigned16 groupsetindex = null;
    private SubSeqOfRegion regiontype = null;
    private SubSeqOfRegion regionaddr = null;
    private SubSeqOfRegion regionsetindex = null;

    /**
     * 默认构造函数
     */
    public MS() {
    }

    /**
     * 设置数据编码
     * 
     * @param dataCode 数据编码
     */
    public void setDataCode(byte[] dataCode) {
        this.dataCode = dataCode;
    }

    @Override
    public int decode(ReverseByteArrayInputStream input) {
        int codeLength = 0;
        AxdrEnum choosen = new AxdrEnum();
        choosen.setConst();

        codeLength += choosen.decode(input);
        this.resetChoices();
        this.choice = MSChoice.fromValue(choosen.getValue());

        if (this.choice == MSChoice.NOM) {
            this.nom = new AxdrNull();
            codeLength += this.nom.decode(input);
            return codeLength;
        }

        if (this.choice == MSChoice.ALLMADDR) {
            this.allmaddr = new AxdrNull();
            codeLength += this.allmaddr.decode(input);
            return codeLength;
        }

        if (this.choice == MSChoice.GROUPMTYPE) {
            this.groupmtype = new SubSeqOfUnsigned8();
            codeLength += this.groupmtype.decode(input);
            return codeLength;
        }

        if (this.choice == MSChoice.GROUPMADDR) {
            this.groupmaddr = new SubSeqOfTsa();
            codeLength += this.groupmaddr.decode(input);
            return codeLength;
        }

        if (this.choice == MSChoice.GROUPSETINDEX) {
            this.groupsetindex = new SubSeqOfUnsigned16();
            codeLength += this.groupsetindex.decode(input);
            return codeLength;
        }

        if (this.choice == MSChoice.REGIONTYPE) {
            this.regiontype = new SubSeqOfRegion();
            codeLength += this.regiontype.decode(input);
            return codeLength;
        }

        if (this.choice == MSChoice.REGIONADDR) {
            this.regionaddr = new SubSeqOfRegion();
            codeLength += this.regionaddr.decode(input);
            return codeLength;
        }

        if (this.choice == MSChoice.REGIONSETINDEX) {
            this.regionsetindex = new SubSeqOfRegion();
            codeLength += this.regionsetindex.decode(input);
            return codeLength;
        }

        throw new RuntimeException("Error decoding AxdrChoice: Identifier matched to no item.");
    }

    @Override
    public int encode(ReverseByteArrayOutputStream output) {
        if (this.dataCode != null) {
            for (int i = this.dataCode.length - 1; i >= 0; i--) {
                try {
                    output.write(this.dataCode[i]);
                } catch (java.io.IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return this.dataCode.length;
        }

        if (this.choice == MSChoice._ERR_NONE_SELECTED) {
            throw new RuntimeException("Error encoding AxdrChoice: No item in choice was selected.");
        }

        int codeLength = 0;

        if (this.choice == MSChoice.REGIONSETINDEX) {
            codeLength += this.regionsetindex.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(7);
            codeLength += c.encode(output);
            return codeLength;
        }

        if (this.choice == MSChoice.REGIONADDR) {
            codeLength += this.regionaddr.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(6);
            codeLength += c.encode(output);
            return codeLength;
        }

        if (this.choice == MSChoice.REGIONTYPE) {
            codeLength += this.regiontype.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(5);
            codeLength += c.encode(output);
            return codeLength;
        }

        if (this.choice == MSChoice.GROUPSETINDEX) {
            codeLength += this.groupsetindex.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(4);
            codeLength += c.encode(output);
            return codeLength;
        }

        if (this.choice == MSChoice.GROUPMADDR) {
            codeLength += this.groupmaddr.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(3);
            codeLength += c.encode(output);
            return codeLength;
        }

        if (this.choice == MSChoice.GROUPMTYPE) {
            codeLength += this.groupmtype.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(2);
            codeLength += c.encode(output);
            return codeLength;
        }

        if (this.choice == MSChoice.ALLMADDR) {
            codeLength += this.allmaddr.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(1);
            codeLength += c.encode(output);
            return codeLength;
        }

        if (this.choice == MSChoice.NOM) {
            codeLength += this.nom.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(0);
            codeLength += c.encode(output);
            return codeLength;
        }

        throw new RuntimeException("Error encoding AxdrChoice: No item in choice was encoded.");
    }

    /**
     * 重置选择
     */
    public void resetChoices() {
        this.choice = MSChoice._ERR_NONE_SELECTED;
        this.nom = null;
        this.allmaddr = null;
        this.groupmtype = null;
        this.groupmaddr = null;
        this.groupsetindex = null;
        this.regiontype = null;
        this.regionaddr = null;
        this.regionsetindex = null;
    }

    /**
     * 编码并保存
     * 
     * @param encodingSizeGuess 编码大小预估
     */
    public void encodeAndSave(int encodingSizeGuess) {
        ReverseByteArrayOutputStream revOStream = new ReverseByteArrayOutputStream();
        revOStream.setBufSize(encodingSizeGuess);
        try {
            encode(revOStream);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("Error encoding MS", e);
        }
        this.dataCode = revOStream.getArray();
    }

    /**
     * 获取选择索引
     * 
     * @return 选择索引
     */
    public MSChoice getChoiceIndex() {
        return this.choice;
    }

    /**
     * 获取选择
     * 
     * @return 选择
     */
    public MSChoice getChoice() {
        return this.choice;
    }

    /**
     * 设置NOM
     * 
     * @param nom 空值
     */
    public void setNom(AxdrNull nom) {
        this.resetChoices();
        this.choice = MSChoice.NOM;
        this.nom = nom;
    }

    /**
     * 设置ALLMADDR
     * 
     * @param allmaddr 空值
     */
    public void setAllmaddr(AxdrNull allmaddr) {
        this.resetChoices();
        this.choice = MSChoice.ALLMADDR;
        this.allmaddr = allmaddr;
    }

    /**
     * 设置GROUPMTYPE
     * 
     * @param groupmtype Unsigned8序列
     */
    public void setGroupmtype(SubSeqOfUnsigned8 groupmtype) {
        this.resetChoices();
        this.choice = MSChoice.GROUPMTYPE;
        this.groupmtype = groupmtype;
    }

    /**
     * 设置GROUPMADDR
     * 
     * @param groupmaddr TSA序列
     */
    public void setGroupmaddr(SubSeqOfTsa groupmaddr) {
        this.resetChoices();
        this.choice = MSChoice.GROUPMADDR;
        this.groupmaddr = groupmaddr;
    }

    /**
     * 设置GROUPSETINDEX
     * 
     * @param groupsetindex Unsigned16序列
     */
    public void setGroupsetindex(SubSeqOfUnsigned16 groupsetindex) {
        this.resetChoices();
        this.choice = MSChoice.GROUPSETINDEX;
        this.groupsetindex = groupsetindex;
    }

    /**
     * 设置REGIONTYPE
     * 
     * @param regiontype Region序列
     */
    public void setRegiontype(SubSeqOfRegion regiontype) {
        this.resetChoices();
        this.choice = MSChoice.REGIONTYPE;
        this.regiontype = regiontype;
    }

    /**
     * 设置REGIONADDR
     * 
     * @param regionaddr Region序列
     */
    public void setRegionaddr(SubSeqOfRegion regionaddr) {
        this.resetChoices();
        this.choice = MSChoice.REGIONADDR;
        this.regionaddr = regionaddr;
    }

    /**
     * 设置REGIONSETINDEX
     * 
     * @param regionsetindex Region序列
     */
    public void setRegionsetindex(SubSeqOfRegion regionsetindex) {
        this.resetChoices();
        this.choice = MSChoice.REGIONSETINDEX;
        this.regionsetindex = regionsetindex;
    }

    /**
     * 获取GROUPMTYPE
     * 
     * @return GROUPMTYPE
     */
    public SubSeqOfUnsigned8 getGroupmtype() {
        return groupmtype;
    }

    /**
     * 获取GROUPMADDR
     * 
     * @return GROUPMADDR
     */
    public SubSeqOfTsa getGroupmaddr() {
        return groupmaddr;
    }

    /**
     * 获取GROUPSETINDEX
     * 
     * @return GROUPSETINDEX
     */
    public SubSeqOfUnsigned16 getGroupsetindex() {
        return groupsetindex;
    }

    /**
     * 获取REGIONTYPE
     * 
     * @return REGIONTYPE
     */
    public SubSeqOfRegion getRegiontype() {
        return regiontype;
    }

    /**
     * 获取REGIONADDR
     * 
     * @return REGIONADDR
     */
    public SubSeqOfRegion getRegionaddr() {
        return regionaddr;
    }

    /**
     * 获取REGIONSETINDEX
     * 
     * @return REGIONSETINDEX
     */
    public SubSeqOfRegion getRegionsetindex() {
        return regionsetindex;
    }

    @Override
    public String toString() {
        if (this.choice == MSChoice.NOM) {
            if (this.nom != null) {
                return "choice: {nom: " + this.nom + "}";
            } else {
                return "choice is nom but nom is null";
            }
        } else if (this.choice == MSChoice.ALLMADDR) {
            if (this.allmaddr != null) {
                return "choice: {allmaddr: " + this.allmaddr + "}";
            } else {
                return "choice is allmaddr but allmaddr is null";
            }
        } else if (this.choice == MSChoice.GROUPMTYPE) {
            if (this.groupmtype != null) {
                return "choice: {groupmtype: " + this.groupmtype + "}";
            } else {
                return "choice is groupmtype but groupmtype is null";
            }
        } else if (this.choice == MSChoice.GROUPMADDR) {
            if (this.groupmaddr != null) {
                return "choice: {groupmaddr: " + this.groupmaddr + "}";
            } else {
                return "choice is groupmaddr but groupmaddr is null";
            }
        } else if (this.choice == MSChoice.GROUPSETINDEX) {
            if (this.groupsetindex != null) {
                return "choice: {groupsetindex: " + this.groupsetindex + "}";
            } else {
                return "choice is groupsetindex but groupsetindex is null";
            }
        } else if (this.choice == MSChoice.REGIONTYPE) {
            if (this.regiontype != null) {
                return "choice: {regiontype: " + this.regiontype + "}";
            } else {
                return "choice is regiontype but regiontype is null";
            }
        } else if (this.choice == MSChoice.REGIONADDR) {
            if (this.regionaddr != null) {
                return "choice: {regionaddr: " + this.regionaddr + "}";
            } else {
                return "choice is regionaddr but regionaddr is null";
            }
        } else if (this.choice == MSChoice.REGIONSETINDEX) {
            if (this.regionsetindex != null) {
                return "choice: {regionsetindex: " + this.regionsetindex + "}";
            } else {
                return "choice is regionsetindex but regionsetindex is null";
            }
        } else {
            return "unknown";
        }
    }
}